package com.liumuxian.exam.service.impl;


import com.liumuxian.exam.dao.ExamInfoDao;
import com.liumuxian.exam.dao.ExamQuestionDao;
import com.liumuxian.exam.dao.QuestionDao;
import com.liumuxian.exam.dao.SubjectAssoetedExamClassifyExamInfoDao;
import com.liumuxian.exam.data.ExamInfoVO;
import com.liumuxian.exam.data.ExamQuestionVO;
import com.liumuxian.exam.pojo.*;
import com.liumuxian.exam.service.ExamInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import util.IdWorker;

import javax.persistence.criteria.*;
import java.util.*;

@Service
@Transactional(readOnly = true)
public class ExamInfoServiceImpl implements ExamInfoService {
    @Autowired
    private ExamInfoDao examInfoDao;
    @Autowired
    private ExamQuestionDao examQuestionDao;
    @Autowired
    private QuestionDao questionDao;
    @Autowired
    private SubjectAssoetedExamClassifyExamInfoDao subjectAssoetedExamClassifyExamInfoDao;
    @Autowired
    private IdWorker idWorker;
    @Transactional
    @Override
    public void save(ExamInfo examInfo){
        examInfo.setId(idWorker.nextId()+"");
        examInfo.setCreatdate(new Date());
        examInfo.setState(1);
        examInfoDao.saveAndFlush(examInfo);
    }



    @Override
    public ExamInfoVO findExamQuestion(String id){
        ExamInfo examInfo = examInfoDao.findById(id).get();
        List<ExamQuestion> examQuestion = examQuestionDao.findByExaminfoid(id);
        Set<String> qid = new HashSet<>();
        examQuestion.forEach(eq -> qid.add(eq.getQuestionid()));
        List<Question> questionList = questionDao.findAllById(qid);
        List<ExamQuestionVO> examQuestionVOList = new ArrayList<>();
        examQuestion.forEach(eq -> {
            questionList.forEach(q -> {
                if(eq.getQuestionid().equals(q.getId())){
                    ExamQuestionVO examQuestionVO = new ExamQuestionVO();
                    examQuestionVO.setQuestionid(q.getId());
                    examQuestionVO.setName(q.getName());
                    examQuestionVO.setType(q.getType());
                    examQuestionVO.setOptions(q.getOptions());
                    examQuestionVO.setAnswer(q.getAnswer());
                    examQuestionVO.setScore(eq.getScore());
                    examQuestionVO.setWeight(eq.getWeight());
                    examQuestionVOList.add(examQuestionVO);
                }
            });
        });
        ExamInfoVO examInfoVO = new ExamInfoVO();
        BeanUtils.copyProperties(examInfo,examInfoVO);
        examInfoVO.setExamInfoVOList(examQuestionVOList);
        return examInfoVO;
    }
    public Page<ExamInfoVO> pageExam(Integer page ,Integer size){
        PageRequest pageRequest =  PageRequest.of(page-1, size);
        Page<ExamInfo> examInfos=examInfoDao.findAll(pageRequest);
        List<ExamInfoVO> eiv = new ArrayList<>();
        examInfos.getContent().forEach(ei -> {
            ExamInfoVO examInfoVO = new ExamInfoVO();
            BeanUtils.copyProperties(ei,examInfoVO);
            eiv.add(examInfoVO);
        });
        return new PageImpl<ExamInfoVO>(eiv, pageRequest, examInfos.getTotalElements());
    }

    public List<ExamInfo> findExamClassify(String subjectassoetedId,String examclassifyId,String examinfoId){
        List<SubjectAssoetedExamClassifyExamInfo> subjectAssoetedExamClassifyExamInfo =  subjectAssoetedExamClassifyExamInfoDao.findAllBySubjectassoetedidAndExamclassifyidAndExaminfoid(subjectassoetedId,examclassifyId,examinfoId);
        Set<String> examinfoIds = new HashSet<>();
        subjectAssoetedExamClassifyExamInfo.forEach(see ->{
            examinfoIds.add(see.getExaminfoid());
        });
        return examInfoDao.findAllById(examinfoIds);
    }
    @Override
    public List<ExamInfo> findAllBySubjectassoetedidAndExamclassifyid(String subjectassoetedId,String Examclassifyid){
        List<SubjectAssoetedExamClassifyExamInfo> subjectAssoetedExamClassifyExamInfos =
                subjectAssoetedExamClassifyExamInfoDao.findAllBySubjectassoetedidAndExamclassifyid(subjectassoetedId,Examclassifyid);
        Map<String,Object> searchMap = new HashMap<>();
        Set<String> examInfoid = new HashSet<>();
        subjectAssoetedExamClassifyExamInfos.forEach(see ->{
            examInfoid.add(see.getExaminfoid());
        });
        searchMap.put("id",examInfoid);
        searchMap.put("state","1");
        Specification<ExamInfo> specification=createSpecification(searchMap);
         return examInfoDao.findAll(specification);
    }
    /**
     * 动态条件构建
     * @param searchMap
     * @return
     */
    private Specification<ExamInfo> createSpecification(Map searchMap) {

        return new Specification<ExamInfo>() {

            @Override
            public Predicate toPredicate(Root<ExamInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicateList = new ArrayList<Predicate>();
                // ID
                if (searchMap.get("id")!=null && !"".equals(searchMap.get("id"))) {
                    //获取cache中的key的class，用于判断key的类型
                    Class<? extends Object> keyClass = null;
                    keyClass = searchMap.get("id").getClass();
                    //判断是不是HashSet类型
                    if(keyClass.equals(HashSet.class)){
                        Path<Object> path = root.get("id");
                        CriteriaBuilder.In<Object> in = cb.in(path);
                        Set<String> id = (Set<String>) searchMap.get("id");
                        id.forEach(i -> in.value(i));
                        predicateList.add(in);
                    }else {
                        predicateList.add(cb.like(root.get("id").as(String.class), "%"+(String)searchMap.get("id")+"%"));
                    }
                }
                // 考试名称
                if (searchMap.get("name")!=null && !"".equals(searchMap.get("name"))) {
                    predicateList.add(cb.like(root.get("name").as(String.class), "%"+(String)searchMap.get("name")+"%"));
                }
                //考试属性
                if (searchMap.get("type")!=null && !"".equals(searchMap.get("type"))) {
                    predicateList.add(cb.like(root.get("type").as(String.class), "%"+(String)searchMap.get("type")+"%"));
                }
                // 状态
                if (searchMap.get("state")!=null && !"".equals(searchMap.get("state"))) {
                    predicateList.add(cb.like(root.get("state").as(String.class), "%"+(String)searchMap.get("state")+"%"));
                }

                return cb.and( predicateList.toArray(new Predicate[predicateList.size()]));

            }
        };

    }
    @Transactional
    @Override
    public void update(ExamInfo examClassify) {
        examInfoDao.saveAndFlush(examClassify);
    }
    @Transactional
    @Override
    public void delete(String id) {
        ExamInfo examClassify = examInfoDao.findById(id).get();
        examClassify.setState(0);
        examInfoDao.saveAndFlush(examClassify);
    }
    @Override
    public ExamInfo findById(String id) {
        return examInfoDao.findById(id).get();
    }

    @Override
    public List<ExamInfo> findAllGesTate(String id, String name, Integer state) {
        return examInfoDao.findAll((Root<ExamInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) -> {
            List<Predicate> predicateList = new ArrayList<Predicate>();
            if (id != null && !StringUtils.isEmpty(id)) {
                predicateList.add(criteriaBuilder.equal(root.get("id"), id));
            }
            if (name != null && !StringUtils.isEmpty(name)) {
                predicateList.add(criteriaBuilder.like(root.get("name"), "%" + name + "%"));
            }
            if (state != null && !StringUtils.isEmpty(state)) {
                predicateList.add(criteriaBuilder.ge(root.get("state"), (Number) state));
            }
            return criteriaBuilder.and( predicateList.toArray(new Predicate[predicateList.size()]));
        });
    }




}
